package com.bio.dao.impl;


import java.io.Serializable;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.annotations.Cache;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.dao.support.DaoSupport;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.bio.dao.Dao;
import com.bio.dao.DaoException;
import com.bio.entity.BaseObject;
import com.bio.utils.Pager;
import com.bio.utils.Pagination;

public class HibernateDaoImpl<T extends Serializable> extends HibernateDaoSupport implements Dao<T> {

	private static Log log = LogFactory.getLog(HibernateDaoImpl.class);
	
    protected Class<T> clazz;
	
    public HibernateDaoImpl() {
    	this.clazz = GenricType.get(this.getClass(), 0);
    }
    
	public T get(Serializable id) {
		return (T) this.getHibernateTemplate().get(this.clazz, id);
	}

	public void remove(Serializable id) throws DaoException {
		T obj = (T) this.getHibernateTemplate().get(this.clazz, id);
		
		if (obj == null) {
			return;
		}
		
		if (obj instanceof BaseObject) {
			((BaseObject) obj).setDeleted(BaseObject.FLAG_DELETED);
			this.getHibernateTemplate().merge(obj);
		} else {
			this.getHibernateTemplate().delete(obj);
		}
	}

	public T save(T obj) throws DaoException {
		 if (log.isDebugEnabled()) {
			 log.debug("����" + obj);
		 }
		 obj = (T) this.getHibernateTemplate().merge(obj);
		 return obj;
	}

	public Pager<T> findAllByPager(Pagination pagination) {
		return new HibernateQuery(this.getSessionFactory(), this.getSession(), this.clazz).setPagination(pagination).query();
	}
	
    public Pager<T> findAllByPagerNoCache(Pagination pagination) {
        return new HibernateQuery(this.getSessionFactory(), this.getSession(), this.clazz).setPagination(pagination).query();
    }
    
	public HibernateQuery<T> newHibernateQuery() {
	    return new HibernateQuery<T>(this.getSessionFactory(), this.getSession(), this.clazz);
	}
	
	public int countByCriteria(final DetachedCriteria detachedCriteria) {
		Long count = (Long) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						return criteria.setProjection(Projections.rowCount())
								.uniqueResult();
					}
				});
		return count.intValue();
	}

	public List<T> findByCriteria(DetachedCriteria detachedCriteria) {
		return getHibernateTemplate().findByCriteria(detachedCriteria);
	}
}
